#include "collections_deque.h"
#include "pika_hal_deque.h"


void collections_deque___init__(PikaObj *self, int maxlen){
    pika_hal_deque_t* que = (pika_hal_deque_t*)pikaMalloc(sizeof(pika_hal_deque_t));

    if (que == NULL){
        obj_raise(self, PIKA_RES_ERR_MEMORY_ERROR, "not enough memory.");
        return;
    }
    int err = pika_hal_deque_init(que, maxlen);
    if (err < 0){
        pikaFree(que, sizeof(pika_hal_deque_t));
        obj_raise(self, PIKA_RES_ERR_MEMORY_ERROR, "not enough memory.");
        return;
    }
    obj_setPtr(self, "queue", que);
}

void collections_deque_append(PikaObj *self, Arg* item){
    pika_hal_deque_t* que = obj_getPtr(self, "queue");
    if (pika_hal_deque_isFull(que)){
        obj_setErrorCode(self, PIKA_RES_ERR_SIGNAL_EVENT_FULL);
        obj_setSysOut(self, "[error] queue is full.");
        return;
    }
    int result = pika_hal_deque_appendTail(que, (void*)arg_copy(item));
    if (result < 0){
        obj_raise(self, PIKA_RES_ERR_MEMORY_ERROR, "not enough memory.");
        return;
    }
}

void collections_deque_appendleft(PikaObj *self, Arg* item){
    pika_hal_deque_t* que = obj_getPtr(self, "queue");
    if (pika_hal_deque_isFull(que)){
        obj_setErrorCode(self, PIKA_RES_ERR_INSUFFICIENT_RESOURCE);
        obj_setSysOut(self, "[error] queue is full.");
        return;
    }
    int result = pika_hal_deque_appendHead(que, (void*)arg_copy(item));
    if (result < 0){
        obj_raise(self, PIKA_RES_ERR_MEMORY_ERROR, "not enough memory.");
        return;
    }
}

Arg* collections_deque_popleft(PikaObj *self){
    pika_hal_deque_t* que = obj_getPtr(self, "queue");
    Arg* item;
    int result = pika_hal_deque_popHead(que, (void**)&item);
    if (result < 0){
        obj_raise(self, PIKA_RES_ERR_EMPTY, "queue is empty.");
        return NULL;
    }
    return item;
}

Arg* collections_deque_pop(PikaObj *self){
    pika_hal_deque_t* que = obj_getPtr(self, "queue");
    Arg* item;
    int result = pika_hal_deque_popTail(que, (void**)&item);
    if (result < 0){
        obj_raise(self, PIKA_RES_ERR_EMPTY, "queue is empty.");
        return NULL;
    }
    return item;
}

int collections_deque_count(PikaObj *self){
    pika_hal_deque_t* que = obj_getPtr(self, "queue");
    return pika_hal_deque_getCount(que);
}

pika_bool collections_deque_is_empty(PikaObj *self){
    pika_hal_deque_t* que = obj_getPtr(self, "queue");
    return pika_hal_deque_isEmpty(que) ? pika_true : pika_false;
}

pika_bool collections_deque_is_full(PikaObj *self){
    pika_hal_deque_t* que = obj_getPtr(self, "queue");
    return pika_hal_deque_isFull(que) ? pika_true : pika_false;
}

void collections_deque___del__(PikaObj *self){
    pika_hal_deque_t* que = obj_getPtr(self, "queue");
    pika_hal_deque_deinit(que);
}